
#if		PLAY_WAV_FILE	== 1

#include "WM8960.h"
//#include "i2c.h"
#include 	"sai.h"
#include 	"stm32h7xx_hal.h"
#include	"main.h"
#include	"stdio.h"


#define WM8960_ADDRESS  0x1a
//#define WM8960_ADDRESS  0x34

extern		I2C_HandleTypeDef hi2c1;

uint16_t	g_WM8960_RECORD = 0;
uint16_t	g_WM8960_PLAY	= 1;

uint32_t AudioTotalSize;  /* This variable holds the total size of the audio file */
uint32_t AudioRemSize;    /* This variable holds the remaining data in audio file */
uint16_t *CurrentPos;     /* This variable holds the current position of audio pointer */

//resgister value
static uint16_t WM8960_REG_VAL[56] =
{  
  0x0097, 0x0097, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000, 0x000A,
  0x01C0, 0x0000, 0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000,
  0x0000, 0x007B, 0x0100, 0x0032, 0x0000, 0x00C3, 0x00C3, 0x01C0,
  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  0x0100, 0x0100, 0x0050, 0x0050, 0x0050, 0x0050, 0x0000, 0x0000,
  0x0000, 0x0000, 0x0040, 0x0000, 0x0000, 0x0050, 0x0050, 0x0000,
  0x0000, 0x0037, 0x004D, 0x0080, 0x0008, 0x0031, 0x0026, 0x00ED
};


void	printf_wm8960_regs(void)
{
	int32_t	i;
	for(i=0;i<14;i++)
	{
	  printf("WM8960_REG_VAL[%2x]:%5x,%5x,%5x,%5x\n", i*4, \
			  WM8960_REG_VAL[i*4], WM8960_REG_VAL[i*4+1], \
			  WM8960_REG_VAL[i*4+2], WM8960_REG_VAL[i*4+3]);
	}
}


uint16_t WM8960_REG_VAL_iic_read[56] =
{
  0
};

void	printf_wm8960_regs_iic_read(void)
{
	int32_t	i;
	for(i=0;i<56;i++)
	{
		WM8960_REG_VAL_iic_read[i] = WM8960_Read_Reg_iic((uint8_t)i);
	}
	for(i=0;i<14;i++)
	{
	  printf("WM8960_REG_VAL_iic_read[%2x]:%5x,%5x,%5x,%5x\n", i*4, \
			  WM8960_REG_VAL_iic_read[i*4], WM8960_REG_VAL_iic_read[i*4+1], \
			  WM8960_REG_VAL_iic_read[i*4+2], WM8960_REG_VAL_iic_read[i*4+3]);
	}
}


/**
  * @brief  Write register of WM8960.
  * @param  reg: The number of resigter which to be read.
  * @param  dat: The data which will be writeen to the register.
  * @retval The value of regsiter.
  */
uint8_t WM8960_Write_Reg(uint8_t reg, uint16_t dat)  {
  
  uint8_t res,I2C_Data[2];
  
  I2C_Data[0] = (reg<<1)|((uint8_t)((dat>>8)&0x0001));  //RegAddr
  I2C_Data[1] = (uint8_t)(dat&0x00FF);                  //RegValue
  
  res = HAL_I2C_Master_Transmit(&hi2c1,(WM8960_ADDRESS<<1),I2C_Data,2,10);
  if(res == HAL_OK)
    WM8960_REG_VAL[reg] = dat;
  
  return res;
}

/**
  * @brief  Read register of WM8960.
  * @param  reg: The number of resigter which to be read.
  * @retval The value of regsiter.
  */
uint16_t WM8960_Read_Reg(uint8_t reg) {
  
  return WM8960_REG_VAL[reg];
}

//uint16_t WM8960_Read_Reg_iic(uint8_t reg) {
//	HAL_StatusTypeDef sta_res;
//	uint8_t I2C_Data[2];
//	I2C_Data[0] = (reg<<1)|((uint8_t)((dat>>8)&0x0001));  //RegAddr
//	I2C_Data[1] = (uint8_t)(dat&0x00FF);                  //RegValue
//	uint16_t reg_val;
//	sta_res = HAL_I2C_Master_Receive(&hi2c1, (WM8960_ADDRESS<<1), (uint8_t *)&I2C_Data, 2, 10);
//	return reg_val;
//}


/**
  * @brief  Initialize WM8960 device.
  * @param  None
  * @retval None
  */
uint8_t WM89060_Init_Play(void)  {

  uint8_t res;
  
  //Reset Device
  res = WM8960_Write_Reg(0x0f, 0x0000);
  if(res != 0)
  {
	  printf("WM8960 initial error !\r\n");
    return res;
  }
  
  //Set Power Source
  res =  WM8960_Write_Reg(0x19, 1<<8 | 1<<7 | 1<<6);
  res += WM8960_Write_Reg(0x1A, 1<<8 | 1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<3);
  res += WM8960_Write_Reg(0x2F, 1<<3 | 1<<2);
  if(res != 0)  {
    printf("Source set fail !!\r\n");
    printf("Error code: %d\r\n",res);
    return res;
  }
  
  //Configure clock
  //MCLK->div1->SYSCLK->DAC/ADC sample Freq = 25MHz(MCLK)/2*256 = 48.8kHz
//  WM8960_Write_Reg(0x04, 0x0000);
  //MCLK->div1->SYSCLK->DAC/ADC sample Freq = 24MHz(MCLK)/6*256 = 15.625kHz
  WM8960_Write_Reg(0x04, 1<<8 | 1<<7 | 1<<5 | 1<<4);
  
  //Configure ADC/DAC
  WM8960_Write_Reg(0x05, 0x0003);
  
  //Configure audio interface
  //I2S format 16 bits word length
//  3:2 WL[1:0] 10 Audio Data Word Length
//  00 = 16 bits
//  01 = 20 bits
//  10 = 24 bits
//  11 = 32 bits (see Note)
//  1:0 FORMAT[1:0] 10 00 = Right justified
//  01 = Left justified
//  10 = I2S Format
//  11 = DSP Mode
  WM8960_Write_Reg(0x07, 0x0002);
  
  //Class D switching freq set
//  WM8960_Write_Reg(0x08, 1<<8 | 1<<6);

  //Configure HP_L and HP_R OUTPUTS
//  LOUT1VOL[6:0] 0000000 LOUT1 Volume
// 1111111 = +6dB
// … 1dB steps down to
// 0110000 = -73dB
// 0101111 to 0000000 = Analogue MUTE
  WM8960_Write_Reg(0x02, 0x0070 | 0x0100);  //LOUT1 Volume Set
  WM8960_Write_Reg(0x03, 0x0070 | 0x0100);  //ROUT1 Volume Set
  
  //Configure SPK_RP and SPK_RN
//  SPKLVOL[6:0] 0000000 SPK_LP/SPK_LN Volume
//  1111111 = +6dB
//  … 1dB steps down to
//  0110000 = -73dB
//  0101111 to 0000000 = Analogue MUTE
  WM8960_Write_Reg(0x28, 0x007f | 0x0100); //Left Speaker Volume
  WM8960_Write_Reg(0x29, 0x007f | 0x0100); //Right Speaker Volume
  
  //Enable the OUTPUTS
  WM8960_Write_Reg(0x31, 0x00F7); //Enable Class D Speaker Outputs
  
  //Configure DAC volume
//  7:0 LDACVOL[7:0] 11111111 Left DAC Digital Volume Control
//  0000 0000 = Digital Mute
//  0000 0001 = -127dB
//  0000 0010 = -126.5dB
//  ... 0.5dB steps up to
  WM8960_Write_Reg(0x0a, 0x00Ff | 0x0100);
  WM8960_Write_Reg(0x0b, 0x00Ff | 0x0100);
  
  //3D
//  WM8960_Write_Reg(0x10, 0x000F);
  
  //Configure MIXER
  WM8960_Write_Reg(0x22, 1<<8 | 0<<7);
  WM8960_Write_Reg(0x25, 1<<8 | 0<<7);
  
//  //#ifdef ALOOPBACK   //先关掉内部路径播放
  WM8960_Write_Reg(0x2d, 1<<7);
  WM8960_Write_Reg(0x2e, 1<<7);


  //Jack Detect
  WM8960_Write_Reg(0x18, 0<<6 | 0<<5);
  WM8960_Write_Reg(0x17, 0x01C3);
  WM8960_Write_Reg(0x30, 0x0009);//0x000D,0x0005
  
  printf("WM8960 initial completed !!\r\n");

  return 0;
}


#define		USE_BOARD_MIC	1


/**
  * @brief  Initialize WM8960
  * @param  None
  * @retval The return value of the I2C transmit function.
  */
uint8_t WM8960_Init_Record(void) {

  uint8_t res;

  //Reset Device
  res = WM8960_Write_Reg(0x0F, 0xFFFF);
  if(res != 0)
    return res;
  else
    printf("WM8960 reset completed !!\r\n");

  //Set Power Source
  #if USE_BOARD_MIC
  res =  WM8960_Write_Reg(0x19, 0x00FC);
  #elif USE_EARPHONE_MIC
  res =  WM8960_Write_Reg(0x19, 0x00D4);
  #endif
  res += WM8960_Write_Reg(0x1A, 0x01F8);
  res += WM8960_Write_Reg(0x2F, 0x003C);

  if(res != 0)  {
    printf("Source set fail !!\r\n");
    printf("Error code: %d\r\n",res);
    return res;
  }

  //Configure clock
  //MCLK->div1->SYSCLK->DAC/ADC sample Freq = 25MHz(MCLK)/2*256 = 48.8kHz
  //WM8960_Write_Reg(0x04, 0x0000);
  //MCLK->div1->SYSCLK->DAC/ADC sample Freq = 24MHz(MCLK)/6*256 = 15.625kHz
  WM8960_Write_Reg(0x04, 1<<8 | 1<<7 | 1<<5 | 1<<4);

  /*********Audio Interface*********/

  //I2S format 16 bits word length
//  WM8960_Write_Reg(0x07, 0x0000);
  WM8960_Write_Reg(0x07, 0x0002);

  /*********PGA*********/
//  5:0 LINVOL[5:0] 010111 Left Input PGA Volume Control
//  111111 = +30dB		0x3f
//  111110 = +29.25dB
//  . . 0.75dB steps down to
//  100100 = 10db		0x24
//  010111 = 0db		0x17
//  000000 = -17.25dB	0x00
  //Input PGA
  WM8960_Write_Reg(0x00, 0x003f | 0x0100);//0x003F
  WM8960_Write_Reg(0x01, 0x003f | 0x0100);//0x003F

  //Input Signal Path
  #if USE_BOARD_MIC
  WM8960_Write_Reg(0x20, 0x0008 | 0x0100);
  WM8960_Write_Reg(0x21, 0x0008 | 0x0100);
  #elif USE_EARPHONE_MIC
  WM8960_Write_Reg(0x20, 0x0000);
  WM8960_Write_Reg(0x21, 0x0008 | 0x0100);
  #endif

  //Input Boost Mixer
  WM8960_Write_Reg(0x2B, 0x0000);
  WM8960_Write_Reg(0x2C, 0x0000);

  /*********ADC*********/

  //ADC Control //ADC High Pass Filter
  //WM8960_Write_Reg(0x05, 0x000a);
  WM8960_Write_Reg(0x05, 0x0000);

  //ADC Digital Volume Control
//  7:0 LADCVOL[7:0] 11000011 Left ADC Digital Volume Control
//  0000 0000 = Digital Mute
//  0000 0001 = -97dB
//  0000 0010 = -96.5dB
//  ... 0.5dB steps up to
//  1111 1111 = +30dB
//  WM8960_Write_Reg(0x15, 0x00C3 | 0x0100);		//0db
//  WM8960_Write_Reg(0x16, 0x00C3 | 0x0100);
  WM8960_Write_Reg(0x15, 0x00ff | 0x0100);			//30db
  WM8960_Write_Reg(0x16, 0x00ff | 0x0100);

  #if USE_BOARD_MIC
//  WM8960_Write_Reg(0x17, 0x01C8);		// all 0x00?
  WM8960_Write_Reg(0x17, 0x01C0);
  #elif USE_EARPHONE_MIC
  WM8960_Write_Reg(0x17, 0x01C8);
  #endif

  /*********ALC Control*********/
  //Noise Gate Control
  //WM8960_Write_Reg(0x14, 0x00F9);
  WM8960_Write_Reg(0x14, 0x0000);

  /*********OUTPUT SIGNAL PATH*********/

  //Digital Volume Control
  WM8960_Write_Reg(0x0A, 0x00FF | 0x0100);
  WM8960_Write_Reg(0x0B, 0x00FF | 0x0100);

  //DAC Soft-Mute Control
  WM8960_Write_Reg(0x05, 0x0000);
  WM8960_Write_Reg(0x06, 0x0000);

  //3D Stereo Enhancement Function
  WM8960_Write_Reg(0x10, 0x0000); //No 3D effect

  //Left and Right Output Mixer Mute and Volume Control
//  WM8960_Write_Reg(0x22, 0x0180); //Left DAC and LINPUT3 to Left Output Mixer
//  WM8960_Write_Reg(0x25, 0x0180); //Right DAC and RINPUT3 to Right Output Mixer
//  WM8960_Write_Reg(0x2D, 0x0080); //Left Input Boost Mixer to Left Output Mixer
//  WM8960_Write_Reg(0x2E, 0x0080); //Right Input Boost Mixer to Right Output Mixer

  /*********ANALOGUE OUTPUTS*********/

  //LOUT1/ROUT1 Volume Control
//  WM8960_Write_Reg(0x02, 0x007F | 0x0100);  //Left Volume
//  WM8960_Write_Reg(0x03, 0x007F | 0x0100);  //Right Volume

  /*********ENABLING THE OUTPUTS*********/

  //Analogue Output Control
  WM8960_Write_Reg(0x31, 0x00F7); //Enable Left and right speakers

  return 0;

}


#if		0


//Record flag
typedef enum
{
  NOT_START = 0,
  START_REC = 1,
  PAUSE_REC = 2,
  STOP_REC  = 3
}REC_FLAG;




#define WAV_BUFFER_SIZE 64000
#define PLAY_SIZE 16000
uint8_t WAV_Buffer_Record[WAV_BUFFER_SIZE] = {0};  //The buffer of record.
__IO uint32_t RecDataSize;

REC_FLAG Rec_Flag;        //The flag of recording state

uint32_t WriteSize;       //The byte numbers of writing to file every time.

//uint8_t I2S_Callback_Flag = 0;
//
//uint8_t I2S_Half_Callback_Flag = 0;




/**
  * @brief  Open the WAV file, get the message of the file.
  * @param  None
  * @retval None
  */
void Strat_Record(void) {

  uint8_t res = 0;
//  FRESULT Res;
  static uint32_t	record_stamp = 0;

  Rec_Flag = START_REC;			//NOT_START;

  WriteSize = WAV_BUFFER_SIZE/2;

//  printf("Press JOY_CTRL to start record !!\r\n");
//  while(Rec_Flag == NOT_START)
//  {
//    Key_Control();
//  }
  printf("Record start !\r\n");

//  res = WAV_File_Init();
//  printf("WAV_File_Init = %d\r\n",res);

//  if(res != 0)
//    return;

  HAL_SAI_Receive_DMA(&hsai_BlockB3, WAV_Buffer_Record, WAV_BUFFER_SIZE/2);

  while((Rec_Flag==START_REC)||(Rec_Flag==PAUSE_REC)) {

    if(I2S_Half_Callback_Flag == 1) {
      I2S_Half_Callback_Flag = 0;
//      res = f_write(&WAV_File,WAV_Buffer_Record,WAV_BUFFER_SIZE/2,&WriteSize);
      RecDataSize += WriteSize;
      printf("f_write: %d, WriteSize: %d\r\n", res, WriteSize);
    }

    if(I2S_Callback_Flag == 1) {
      I2S_Callback_Flag = 0;
//      res = f_write(&WAV_File,(WAV_Buffer_Record+(WAV_BUFFER_SIZE/2)),WAV_BUFFER_SIZE/2,&WriteSize);
      RecDataSize += WriteSize;
      printf("f_write: %d, WriteSize: %d\r\n", res, WriteSize);
    }
    else  {
      //Key_Control();
    	if(HAL_GetTick() >= record_stamp + 500)
    	{
    		printf("WAV_Buffer_Record[0]: %d\r\n", WAV_Buffer_Record[0]);
    		record_stamp = HAL_GetTick();
    	}
    	if(RecDataSize >= WAV_BUFFER_SIZE)
    	{
    		Rec_Flag = STOP_REC;
    	    printf("STOP_REC!!\r\n");
    	    HAL_SAI_DMAStop(&hsai_BlockB3);
    	}
    }
  }
//  WAV_Header.riff.ChunkSize = RecDataSize+36;   //File size - 8;
//  WAV_Header.data.ChunkSize = RecDataSize;      //Data size
  printf("RecDataSize=%d\r\n",RecDataSize);

//  f_sync(&WAV_File);
//  Res=f_lseek(&WAV_File,0);										  //offset to file head.
//  printf("res=%d\r\n",Res);
//
//  Res=f_write(&WAV_File,(const void*)(&WAV_Header),sizeof(__WaveHeader),&WriteSize);  //write file head
//  printf("f_write=%d\r\n",Res);
//
//  Res=f_close(&WAV_File);
//	printf("f_close=%d\r\n",Res);

	printf("Record stop\r\n");
}




/**
  * @brief  Starts playing audio stream from a data buffer for a determined size. 
  * @param  pBuffer: Pointer to the buffer 
  * @param  Size: Number of audio data BYTES.
  * @retval None
  */
uint32_t AudioFlashPlay(uint16_t* pBuffer, uint32_t FullSize, uint32_t StartAdd)
{ 
  AUDIO_Play((uint16_t*)pBuffer, (uint32_t)(FullSize - StartAdd));
  return 0;
}

/**
  * @brief  Starts playing audio stream from a data buffer for a determined size. 
  * @param  pBuffer: Pointer to the buffer 
  * @param  Size: Number of audio data BYTES.
  * @retval None
  */
uint32_t AUDIO_Play(uint16_t* pBuffer, uint32_t Size)
{
  uint8_t res;
  /* Set the total number of data to be played (count in half-word) */
  AudioTotalSize = Size;
  
  /* Update the Media layer and enable it for play */
  //res = HAL_I2S_Transmit_DMA(&hi2s2,pBuffer, (uint32_t)(DMA_MAX(Size/2)));
  printf("DMA_MAX(Size/2): %d\r\n",DMA_MAX(Size/2));
  
  /* Update the remaining number of data to be played */
  AudioRemSize = Size/2 - DMA_MAX(AudioTotalSize);
  printf("AudioRemSize = %d\r\n",AudioRemSize);
  
  /* Update the current audio pointer position */
  CurrentPos = pBuffer + DMA_MAX(AudioTotalSize);
  
  return res;
}

#endif

#endif

